package com.honey.mybatis.generator;

import com.honey.compilation.java.Field;
import com.honey.compilation.java.Method;
import com.honey.compilation.java.Parameter;
import com.honey.core.dbmapping.structure.Column;
import com.honey.core.dbmapping.structure.Structure;
import com.honey.core.types.FullyQualifiedJavaType;
import com.honey.core.utils.StringUtility;
import com.honey.generator.java.AbstractClassName;
import com.honey.mybatis.generator.condition.ConditionConstant;
import com.honey.mybatis.generator.criteria.CriteriaConstant;
import com.honey.mybatis.generator.dependent.DependentMapperId;
import com.honey.mybatis.generator.dependent.DependentModel;
import com.honey.mybatis.generator.inversion.InversionModel;

public abstract class AbstractMybatis extends AbstractClassName {
	
	protected MybatisPlugin mybatisPlugin;
	
	/**
	 * 慎用默认的构造函数.
	 */
	public AbstractMybatis() {
	}
	
	/**
	 * 构造函数
	 * @param belongPlugin
	 */
	public AbstractMybatis(MybatisPlugin belongPlugin) {
		super(belongPlugin);
		mybatisPlugin = belongPlugin;
	}
	
	/**
	 * 注入模型
	 * @return
	 */
	public InversionModel getInversionModel(){
		return mybatisPlugin.getInversionModel() ;
	}
	
	/**
	 * 依赖模型
	 * @return
	 */
	public DependentModel getDependentModel(){
		return mybatisPlugin.getDependentModel();
	}
	
	/**
	 * 获取mapper id
	 * @return
	 */
	public DependentMapperId getMapperId(){
		return mybatisPlugin.getDependentModel().getDependentMapperId();
	}
	
//===================================Type==========================================================
	/**
	 * 创建class的类型
	 * @param schema 数据库对象
	 * @param packageName 包的名称
	 * @param postfix 类的后缀名称
	 * @param generic 泛型
	 * @return
	 */
	protected FullyQualifiedJavaType getClassType(Structure schema,String packageName,String postfix,String generic){
		return getClassType(schema, packageName, postfix, generic, false);
	}
	
	/**
	 * 创建class的类型
	 * @param schema 数据库对象
	 * @param packageName 包的名称
	 * @param postfix 类的后缀名称
	 * @param generic 泛型
	 * @param isBlob 是否包含大字段
	 * @return
	 */
	private FullyQualifiedJavaType getClassType(Structure schema,String packageName,String postfix, String generic, boolean isBlob){
		FullyQualifiedJavaType answer = null;
		String JavaProperty = "";
		if(schema != null ) JavaProperty = schema.getJavaProperty();
		String javaProperty =getClassName(JavaProperty,postfix, isBlob?mybatisPlugin.getBlobSuffix():null);
		if(StringUtility.stringHasValue(generic))
			javaProperty += generic;
		answer = new FullyQualifiedJavaType(packageName,javaProperty);
		return answer;
	}
	
	/**
	 * 获取状态枚举类型(状态枚举在Model里面,所以需要schema传入进来计算model类的名称)
	 * @param schema
	 * @param enumType
	 * @return
	 */
	protected FullyQualifiedJavaType getStateEnumType(Structure schema, Structure enumType ){
		//String name = mybatisPlugin.getJavaNameCalculator().classNameCalculator(enumType.getJavaProperty(),mybatisPlugin.getEnumClassSuffix());
		//return new FullyQualifiedJavaType(name);
		return getClassType(enumType, getModelPrimitiveClassType(schema).getFullyQualifiedName(), mybatisPlugin.getEnumClassSuffix(), null);
	}
	
	/**
	 * 获取实体接口类型
	 * @param schema
	 * @return
	 */
	protected FullyQualifiedJavaType getEntityInterfaceType(Structure schema){
		return new FullyQualifiedJavaType(mybatisPlugin.getEntityTargetPackage(),getEntityInterfaceName(schema));
	}
	
	/**
	 * 获取实体类型,对象可能会提升到父类 
	 * @param schema
	 * @return
	 */
	public FullyQualifiedJavaType getEntityClassType(Structure schema ){
		return mybatisPlugin.getDependentModel().getEntityClassType(mybatisPlugin, schema);
		//return getClassType(schema, mybatisPlugin.getEntityTargetPackage(),mybatisPlugin.getEntityClassSuffix(),null);
	}
	
	/**
	 * 获取实体类型,对象不会提升到父类
	 * @param schema
	 * @return
	 */
	public FullyQualifiedJavaType getEntityPrimitiveClassType(Structure schema ){
		return getClassType(schema, mybatisPlugin.getEntityTargetPackage(),mybatisPlugin.getEntityClassSuffix(),null);
	}
	
	/**
	 * 大字段实体类型 
	 * @param schema
	 * @return
	 */
	protected FullyQualifiedJavaType getBlobEntityClassType(Structure schema ){
		return getClassType(schema, mybatisPlugin.getEntityTargetPackage(),mybatisPlugin.getEntityClassSuffix(),null,true);
	}
	
	/**
	 * 模型类型，对象可能提升到父类 
	 * @param schema
	 * @return
	 */
	public FullyQualifiedJavaType getModelClassType(Structure schema ){
		return mybatisPlugin.getDependentModel().getModelClassType(mybatisPlugin, schema);
		//return getClassType(schema, mybatisPlugin.getModelTargetPackage(),mybatisPlugin.getModelClassSuffix(),null);
	}
	
	/**
	 * 获取原始的模型名称,对象不会提升到父类
	 * @param schema
	 * @return
	 */
	public FullyQualifiedJavaType getModelPrimitiveClassType(Structure schema ){
		return getClassType(schema, mybatisPlugin.getModelTargetPackage(),mybatisPlugin.getModelClassSuffix(),null);
	}
	
	/**
	 * 接口类型 
	 * @param schema
	 * @return
	 */
	protected FullyQualifiedJavaType getInterfaceClassType(Structure schema,String generic){
		return getClassType(schema, mybatisPlugin.getDaoInterfacePackage(),mybatisPlugin.getDaoInterfaceSuffix(),generic);
	}
	
	/**
	 * 实现类
	 * @param schema
	 * @param generic
	 * @return
	 */
	protected FullyQualifiedJavaType getImplementsClassType(Structure schema,String generic){
		return getClassType(schema, mybatisPlugin.getDaoImplementsPackage(),mybatisPlugin.getDaoImplementsSuffix(),generic);
	}
	
	
	/**
	 * Condition 类
	 * @param schema
	 * @param generic
	 * @return
	 */
	protected FullyQualifiedJavaType getConditionClassType(Structure schema,String generic){
		return new FullyQualifiedJavaType(mybatisPlugin.getModelTargetPackage(),ConditionConstant.CONDITION_CLASS_NAME+"<T extends "+CriteriaConstant.GENERATED_CRITERIA_CLASS_NAME+"<?, ?>>");
		//return getClassType(schema, mybatisPlugin.getInterfaceTargetPackage(),mybatisPlugin.getInterfaceClassPostfix(),generic);
	}
	
	/**
	 * Condition 类,对象可能提升到父类
	 * @param schema
	 * @param generic
	 * @return
	 */
	public FullyQualifiedJavaType getConditionClassType(Structure schema){
		return mybatisPlugin.getDependentModel().getConditionClassType(mybatisPlugin, schema);
		//return new FullyQualifiedJavaType(mybatisPlugin.getModelTargetPackage(),ConditionConstant.CONDITION_CLASS_NAME+"<"+getModelClassName(schema)+">");
	}
	
	/**
	 * Condition 类,对象可不会提升到父类
	 * @param schema
	 * @return
	 */
	public FullyQualifiedJavaType getConditionPrimitiveClassType(Structure schema){
		return new FullyQualifiedJavaType(mybatisPlugin.getModelTargetPackage(),ConditionConstant.CONDITION_CLASS_NAME+"<"+getModelClassName(schema)+">");
	}
	
	
	/**
	 * 获取表列枚举类的名称
	 * @param schema
	 * @return
	 */
	protected FullyQualifiedJavaType getTableColumnEnumClassType(Structure schema){
		return getClassType(schema, null, mybatisPlugin.getModelTableFieldEnumSuffix(), null);
	}
	
	/**
	 * 获取列的类型
	 * @param column
	 * @return
	 */
	protected FullyQualifiedJavaType getFieldType(Structure schema, Column column){
		FullyQualifiedJavaType type = column.getFullyQualifiedJavaType();
		if( column.getEnumSchema() != null ){
			type = getStateEnumType(schema , column.getEnumSchema() );
		}
		return type;
	}
	
	/**
	 * 获取base dao的类型
	 * @param schema
	 * @return
	 */
	protected FullyQualifiedJavaType getBaseDaoImplementsClassType(Structure schema,String generic){
		FullyQualifiedJavaType answer = null;
		String javaProperty =getClassName(mybatisPlugin.getBaseDaoName(),mybatisPlugin.getDaoImplementsSuffix() );
		if(StringUtility.stringHasValue(generic))
			javaProperty += generic;
		answer = new FullyQualifiedJavaType(mybatisPlugin.getBaseDaoPackage(),javaProperty);
		return answer ;
		
		//return getClassType(null, mybatisPlugin.getBaseDaoPackage(), mybatisPlugin.getBaseDaoName(), generic) ;
	}
	
	/**
	 * 接口类型 
	 * @param schema
	 * @return
	 */
	protected FullyQualifiedJavaType getBaseDaoInterfaceClassType(Structure schema,String generic){
		return getClassType(null, mybatisPlugin.getDaoInterfacePackage(),mybatisPlugin.getBaseDaoName(),generic);
	}
	

//===================================Name==========================================================
	/**
	 * 获取类的名称
	 * @param column
	 * @return
	 */
	protected String getClassName(Structure schema,String suffix){
		//return mybatisPlugin.getJavaNameCalculator().classNameCalculator(schema.getJavaProperty(),suffix);
		return getClassName(schema.getJavaProperty(),suffix);
	}
	
	/**
	 * 获取内部类名称
	 * @param schema
	 * @return
	 */
	protected String getStateEnumName(Structure schema){
		return getClassName(schema, mybatisPlugin.getEnumClassSuffix());
	}
	
	/**
	 * 获取实体类型名称,可能提升到父类
	 * @param schema
	 * @return
	 */
	public String getEntityClassName(Structure schema ){
		return mybatisPlugin.getDependentModel().getEntityClassName(mybatisPlugin, schema);
		//return getClassName(schema, mybatisPlugin.getEntityClassSuffix());
	}
	
	/**
	 * 获取实体类型名称
	 * @param schema
	 * @return
	 */
	public String getEntityPrimitiveClassName(Structure schema ){
		return getClassName(schema, mybatisPlugin.getEntityClassSuffix());
	}
	
	
	/**
	 * 实体作为变量时的名称
	 * @param schema
	 * @return
	 */
	public String getEntityVariableName(Structure schema ){
		return mybatisPlugin.getDependentModel().getEntityVariable(mybatisPlugin, schema);
		//return getVariableName(schema.getJavaProperty(),mybatisPlugin.getEntityClassSuffix());
	}
	
	/**
	 * 获取大字段实体类型名称
	 * @param schema
	 * @return
	 */
	protected String getBlobEntityClassName(Structure schema ){
		return getClassName(schema.getJavaProperty(), mybatisPlugin.getEntityClassSuffix(),mybatisPlugin.getBlobSuffix() );
	}
	
	/**
	 * 大字段实体作为变量时的名称
	 * @param schema
	 * @return
	 */
	protected String getBlobEntityVariableName(Structure schema ){
		return getVariableName(schema.getJavaProperty(),mybatisPlugin.getEntityClassSuffix(),mybatisPlugin.getBlobSuffix());
	}
	
	/**
	 * 模型类型名称,可能名称提升到父类
	 * @param schema
	 * @return
	 */
	public String getModelClassName(Structure schema ){
		return mybatisPlugin.getDependentModel().getModelClassName(mybatisPlugin, schema);
		//return getClassName(schema, mybatisPlugin.getModelClassSuffix());
	}
	
	/**
	 * 模型类型名称,不会发生名称提升
	 * @param schema
	 * @return
	 */
	public String getModelPrimitiveClassName(Structure schema ){
		return getClassName(schema, mybatisPlugin.getModelClassSuffix());
	}
	
	
	/**
	 * 模型类作为变量时的名称
	 * @param schema
	 * @return
	 */
	protected String getModelVariableName(Structure schema ){
		return getVariableName(schema.getJavaProperty(),mybatisPlugin.getModelClassSuffix());
	}
	
	/**
	 * 接口类型名称
	 * @param schema
	 * @return
	 */
	protected String getInterfaceClassName(Structure schema ){
		return getClassName(schema, mybatisPlugin.getDaoInterfaceSuffix());
	}
	
	/**
	 * 模型类作为变量时的名称
	 * @param schema
	 * @return
	 */
	protected String getInterfaceVariableName(Structure schema ){
		return getVariableName(schema.getJavaProperty(),mybatisPlugin.getDaoInterfaceSuffix());
	}
	
	/**
	 * 实现类名称
	 * @param schema
	 * @return
	 */
	protected String getImplementsClassName(Structure schema ){
		return getClassName(schema, mybatisPlugin.getDaoImplementsSuffix());
	}
	
	/**
	 * 实现类作为变量时的名称
	 * @param schema
	 * @return
	 */
	protected String getImplementsVariableName(Structure schema ){
		return getVariableName(schema.getJavaProperty(),mybatisPlugin.getDaoImplementsSuffix());
	}
	
	/**
	 * 获取属性的名称
	 * @param column
	 * @return
	 */
	protected String getFieldName(Column column){
		return mybatisPlugin.getJavaNameCalculator().fieldNameCalculator(column.getJavaProperty());
	}
	
	/**
	 * 获取方法的名称
	 * @param column
	 * @return
	 */
	protected String getMethodName(Column column){
		return mybatisPlugin.getJavaNameCalculator().methodNameCalculator(column.getJavaProperty());
	}
	
	/**
	 * 获取base dao 的名称
	 * @param schema
	 * @return
	 */
	protected String getBaseDaoImplementsClassString(Structure schema){
		return  getClassName(mybatisPlugin.getBaseDaoName(),mybatisPlugin.getDaoImplementsSuffix() );
	}

	/**
	 * 接口类型 
	 * @param schema
	 * @return
	 */
	protected String getBaseDaoInterfaceClassName(Structure schema){
		return  getClassName(mybatisPlugin.getBaseDaoName());
	}
	
	
	
	/**
	 * 获取实体接口的名称
	 * @param schema
	 * @return
	 */
	protected String getEntityInterfaceName(Structure schema){
		return "Entity";
	}
	
	/**
	 * 获取表列枚举类的名称
	 * @param schema
	 * @return
	 */
	protected String getTableColumnEnumClassName(Structure schema){
		
		return getClassName(schema, mybatisPlugin.getModelTableFieldEnumSuffix());
	}
	
	protected void setBaseType(Field field ){
		field.setBaseType(! mybatisPlugin.getProjectEnvironmentHolder().isForcePrimitiveType() );
	}

	protected void setBaseType(Method method ){
		method.setBaseType(! mybatisPlugin.getProjectEnvironmentHolder().isForcePrimitiveType() );
	}
	
	protected void setBaseType(Parameter parameter ){
		parameter.setBaseType(! mybatisPlugin.getProjectEnvironmentHolder().isForcePrimitiveType() );
	}
	
}
